/*
 * Copyright (C) 2014 singwhatiwanna(任玉刚) <singwhatiwanna@gmail.com>
 *
 * collaborator:田啸,宋思宇,Mr.Simple
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ryg.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public final class SoLibExtManager {

    private static final String TAG = "SoLibExtManager";
    private ExecutorService mSoExecutor = Executors.newCachedThreadPool();
    private static SoLibExtManager sInstance = new SoLibExtManager();
    private static String sNativeLibDir = "";

    public SoLibExtManager() {
    }

    public static SoLibExtManager getSoLoader() {
        return sInstance;
    }

    private String getCpuName() {
        try {
            FileReader e = new FileReader("/proc/cpuinfo");
            BufferedReader br = new BufferedReader(e);
            String text = br.readLine();
            br.close();
            String[] array = text.split(":\\s+", 2);
            if(array.length >= 2) {
                return array[1];
            }
        } catch (FileNotFoundException var5) {
            var5.printStackTrace();
        } catch (IOException var6) {
            var6.printStackTrace();
        }

        return null;
    }

    @SuppressLint({"DefaultLocale"})
    private String getCpuArch(String cpuName) {
        String cpuArchitect = "armeabi";
//        if(cpuName.toLowerCase().contains("arm") && cpuName.toLowerCase().contains("7")){
//            cpuArchitect = "armeabi-v7";
//        }
        if(cpuName.toLowerCase().equals("0")){
            cpuArchitect = "armeabi";
        }else if(cpuName.toLowerCase().contains("arm")) {
            cpuArchitect = "armeabi";
        }else if(cpuName.toLowerCase().contains("x86")) {
            cpuArchitect = "x86";
        } else if(cpuName.toLowerCase().contains("mips")) {
            cpuArchitect = "mips";
        }

        return cpuArchitect;
    }

    public void copyPluginSoLib(Context context, String dexPath, String nativeLibDir) {
        String cpuName = this.getCpuName();
        String cpuArchitect = this.getCpuArch(cpuName);
        sNativeLibDir = nativeLibDir;
        Log.d(TAG, "cpuArchitect: " + cpuArchitect);
        long start = System.currentTimeMillis();

        try {
            ZipFile end = new ZipFile(dexPath);
            Enumeration entries = end.entries();

            while(entries.hasMoreElements()) {
                ZipEntry zipEntry = (ZipEntry)entries.nextElement();
                if(!zipEntry.isDirectory()) {
                    String zipEntryName = zipEntry.getName();
                    if(zipEntryName.endsWith(".so") && zipEntryName.contains(cpuArchitect+"/")) {
                        long lastModify = zipEntry.getTime();
                        if(lastModify == DLConfigs.getSoLastModifiedTime(context, zipEntryName)) {
                            Log.d(TAG, "skip copying, the so lib is exist and not change: " + zipEntryName);
                        } else {
                            this.mSoExecutor.execute(new SoLibExtManager.CopySoTask(context, end, zipEntry, lastModify));
                        }
                        break;
                    }
                }
            }
        } catch (IOException var14) {
            var14.printStackTrace();
        }

        long end1 = System.currentTimeMillis();
        Log.d(TAG, "### copy so time : " + (end1 - start) + " ms");
    }

    private class CopySoTask implements Runnable {
        private String mSoFileName;
        private ZipFile mZipFile;
        private ZipEntry mZipEntry;
        private Context mContext;
        private long mLastModityTime;

        CopySoTask(Context context, ZipFile zipFile, ZipEntry zipEntry, long lastModify) {
            this.mZipFile = zipFile;
            this.mContext = context;
            this.mZipEntry = zipEntry;
            this.mSoFileName = this.parseSoFileName(zipEntry.getName());
            this.mLastModityTime = lastModify;
        }

        private final String parseSoFileName(String zipEntryName) {
            return zipEntryName.substring(zipEntryName.lastIndexOf("/") + 1);
        }

        private void writeSoFile2LibDir() throws IOException {
            InputStream is = null;
            FileOutputStream fos = null;
            is = this.mZipFile.getInputStream(this.mZipEntry);
            fos = new FileOutputStream(new File(SoLibExtManager.sNativeLibDir, this.mSoFileName));
            this.copy(is, fos);
        }

        public void copy(InputStream is, OutputStream os) throws IOException {
            if(is != null && os != null) {
                BufferedInputStream bis = new BufferedInputStream(is);
                BufferedOutputStream bos = new BufferedOutputStream(os);
                int size = this.getAvailableSize(bis);
                byte[] buf = new byte[size];
                boolean i = false;

                int i1;
                while((i1 = bis.read(buf, 0, size)) != -1) {
                    bos.write(buf, 0, i1);
                }

                bos.flush();
                bos.close();
                bis.close();
            }
        }

        private int getAvailableSize(InputStream is) throws IOException {
            if(is == null) {
                return 0;
            } else {
                int available = is.available();
                return available <= 0?1024:available;
            }
        }

        public void run() {
            try {
                this.writeSoFile2LibDir();
                DLConfigs.setSoLastModifiedTime(this.mContext, this.mZipEntry.getName(), this.mLastModityTime);
                Log.i(SoLibExtManager.TAG, "copy so lib success: " + this.mZipEntry.getName());
            } catch (IOException var2) {
                Log.e(SoLibExtManager.TAG, "copy so lib failed: " + var2.toString());
                var2.printStackTrace();
            }

        }
    }
}
